package com.alibaba.citrus.ots.application.report.ability.facade.service;

import com.alibaba.citrus.ots.application.report.ability.repository.OrderProgressMonitorReportQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.utils.DomUtil;
import com.alibaba.citrus.ots.application.report.ability.utils.SubtotalViewVOUtil;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.dto.request.IdQueryRequest;
import com.epoch.app.crplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.otsapplicationreportsdk.model.dto.OrderProgressMonitorReportSDO;
import com.epoch.app.otsapplicationreportsdk.model.dto.OrderProgressMonitorReportVO;
import com.epoch.app.otsapplicationreportsdk.model.dto.QueryOrderMonitorReportRequest;
import com.epoch.app.otsapplicationreportsdk.model.dto.SubtotalViewVO;
import com.epoch.app.otsapplicationreportsdk.orderprogressmonitorreportquery.service.OrderProgressMonitorReportQueryService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zhoubc
 * @description: TODO
 * @date 2022/1/6 20:24
 */
@Primary
@Component
public class OrderProgressMonitorReportServiceImpl implements OrderProgressMonitorReportQueryService {

    private static Log log = Log.getLogger(OrderProgressMonitorReportServiceImpl.class);

    private static final String[] PARENT_ORG_ID_TO_FILTER = new String[]{"297608902236651725", "298622222733362149"};

    @Resource
    OrderProgressMonitorReportQueryRepository orderProgressMonitorReportQueryRepository;

    @Resource
    private OrganizationQueryService organizationQueryService;

    @Override
    @FacadeInvoker
    public Result<List<OrderProgressMonitorReportVO>> pageQueryOrderProgressMonitorReportList(QueryOrderMonitorReportRequest queryOrderMonitorReportRequest) {
        if (StringUtil.isBlank(queryOrderMonitorReportRequest.getStatisticalDate())) {
            throw new FacadeException(ErrorMessage.code("OTS-01-010-01-15-001"));
        }
        if (StringUtil.isNotEmpty(queryOrderMonitorReportRequest.getParentOrganizationId()) && CollectionUtils.isNotEmpty(queryOrderMonitorReportRequest.getOrganizationIds())) {
            queryOrderMonitorReportRequest.setParentOrganizationId(null);
        }

        List<String> filterOrganizationIds = getFilterOrgnizationIds(queryOrderMonitorReportRequest.getBizType());
        queryOrderMonitorReportRequest.setFilterOrganizationIds(filterOrganizationIds);
        PageResult<List<OrderProgressMonitorReportSDO>> pageResult = orderProgressMonitorReportQueryRepository.pageQueryOrderMonitorReportList(queryOrderMonitorReportRequest);
        List<OrderProgressMonitorReportSDO> listResult = pageResult.getContent();
        List<OrderProgressMonitorReportVO> converterResult = null;
        Result<List<SubtotalViewVO>> viewResult = null;
        log.info("pageQueryOrderProgressMonitorReportList_QueryResult:{}",JSONObject.toJSONString(listResult));
        //查询为空，初始化列表数据
        if (CollectionUtils.isEmpty(listResult)) {
            converterResult = new ArrayList<>();
            viewResult = initSubtotalViewVO();
        } else {
            //数据格式转换
            converterResult = converterVO(listResult, false);
            //查询表头的数据统计
            Result<List<SubtotalViewVO>> response = getSubtotalViewData(queryOrderMonitorReportRequest);
            viewResult = response;
        }

        Map<String, Object> ext = new HashMap<>();
        ext.put("statistic", viewResult.getResult());
        String progressValue = DomUtil.getProgressValue(queryOrderMonitorReportRequest.getStatisticalDate());
        ext.put("progress", progressValue.substring(0, progressValue.length() - 1));
        Result result = Result.listSuccess(converterResult, pageResult.getTotal());
        result.setExt(ext);
        return result;
    }

    /**
     * 根据组织id过滤查询结果
     * 0411需求，报表中过滤电商和牛要客数据
     * 过滤parent_id为297608902236651725（电商大区）和298622222733362149(垂直重客大区）的数据
     *
     */
    private List<String> getFilterOrgnizationIds(Integer filterType) {
        List<String> filterOrganizationIds = new ArrayList<>();
        //查询需要过滤的组织层级
        IdQueryRequest idQueryRequest = new IdQueryRequest();
        idQueryRequest.setType(filterType);
        for (String parentOrgID : PARENT_ORG_ID_TO_FILTER) {
            idQueryRequest.setId(parentOrgID);
            Result<List<OrganizationSDO>> childOrganizationList = organizationQueryService.getDownQueryOrganization(idQueryRequest);
            log.info("filterResultByOrgnizationID={},childOrganizationList={}", parentOrgID, JSONObject.toJSONString(childOrganizationList));
            if (CollectionUtils.isEmpty(childOrganizationList.getResult())) {
                continue;
            }
            filterOrganizationIds.addAll(childOrganizationList.getResult().stream().map(x->x.getId()).collect(Collectors.toList()));
        }
        return filterOrganizationIds;
    }

    @Override
    @FacadeInvoker
    public Result<List<OrderProgressMonitorReportVO>> pageQueryOrderProgressMonitorReportListForExport(QueryOrderMonitorReportRequest queryOrderMonitorReportRequest) {
        if (StringUtil.isBlank(queryOrderMonitorReportRequest.getStatisticalDate())) {
            throw new FacadeException(ErrorMessage.code("OTS-01-010-01-15-001"));
        }
        if (StringUtil.isNotEmpty(queryOrderMonitorReportRequest.getParentOrganizationId()) && CollectionUtils.isNotEmpty(queryOrderMonitorReportRequest.getOrganizationIds())) {
            queryOrderMonitorReportRequest.setParentOrganizationId(null);
        }
        List<String> filterOrganizationIds = getFilterOrgnizationIds(queryOrderMonitorReportRequest.getBizType());
        queryOrderMonitorReportRequest.setFilterOrganizationIds(filterOrganizationIds);
        PageResult<List<OrderProgressMonitorReportSDO>> pageResult = orderProgressMonitorReportQueryRepository.pageQueryOrderMonitorReportList(queryOrderMonitorReportRequest);
        List<OrderProgressMonitorReportSDO> listResult = pageResult.getContent();
        List<OrderProgressMonitorReportVO> converterResult = null;
        Result<List<SubtotalViewVO>> viewResult = null;
        //查询为空，初始化列表数据
        if (CollectionUtils.isEmpty(listResult)) {
            converterResult = new ArrayList<>();
            viewResult = initSubtotalViewVO();
        } else {
            //数据格式转换
            converterResult = converterVO(listResult, true);
            //查询表头的数据统计
            Result<List<SubtotalViewVO>> response = getSubtotalViewData(queryOrderMonitorReportRequest);
            viewResult = response;

            //最后一页增加统计数据
            if (isLastPage(converterResult, queryOrderMonitorReportRequest)) {
                //最后一页
                OrderProgressMonitorReportVO vo = buildLastPageData(viewResult);
                converterResult.add(vo);
            }
        }

        Map<String, Object> ext = new HashMap<>();
        ext.put("statistic", viewResult.getResult());
        String progressValue = DomUtil.getProgressValue(queryOrderMonitorReportRequest.getStatisticalDate());
        ext.put("progress", progressValue.substring(0, progressValue.length() - 1));
        Result result = Result.listSuccess(converterResult, pageResult.getTotal());
        result.setExt(ext);
        return result;
    }

    private OrderProgressMonitorReportVO buildLastPageData(Result<List<SubtotalViewVO>> viewResult) {
        OrderProgressMonitorReportVO vo = new OrderProgressMonitorReportVO();
        vo.setOrganizationName("合计:");

        List<SubtotalViewVO> subtotalViewVOList = viewResult.getResult();
        Map<String, SubtotalViewVO> map = subtotalViewVOList.stream().collect(Collectors.toMap(SubtotalViewVO::getLabel, SubtotalViewVO -> SubtotalViewVO));
        //月计划日均量
        SubtotalViewVO planDailyAverage = map.get("月计划日均量");
        if (Objects.nonNull(planDailyAverage) && Objects.nonNull(planDailyAverage.getValue())) {
            vo.setPlanDailyAverage(planDailyAverage.getValue() + planDailyAverage.getDecimal());
        } else {
            vo.setPlanDailyAverage("0");
        }
        //当日应下单量
        SubtotalViewVO shouldOrderQuantity = map.get("当日应下单量");
        if (Objects.nonNull(shouldOrderQuantity) && Objects.nonNull(shouldOrderQuantity.getValue())) {
            vo.setShouldOrderQuantity(shouldOrderQuantity.getValue() + shouldOrderQuantity.getDecimal());
        } else {
            vo.setShouldOrderQuantity("0");
        }
        //当日订单量合计
        SubtotalViewVO quantity = map.get("当日订单量合计");
        if (Objects.nonNull(quantity) && Objects.nonNull(quantity.getValue())) {
            vo.setOrderQuantity(quantity.getValue() + quantity.getDecimal());
        } else {
            vo.setOrderQuantity("0");
        }
        //日订单差量
        SubtotalViewVO differQuantity = map.get("日订单差量");
        if (Objects.nonNull(differQuantity) && Objects.nonNull(differQuantity.getValue())) {
            vo.setDifferQuantity(differQuantity.getValue() + differQuantity.getDecimal());
        } else {
            vo.setDifferQuantity("0");
        }
        //当日达成率
        SubtotalViewVO completeRate = map.get("当日达成率");
        if (Objects.nonNull(completeRate) && Objects.nonNull(completeRate.getValue())
                && Objects.nonNull(completeRate.getDecimal()) && Objects.nonNull(completeRate.getUnit())) {
            vo.setCompleteRate(completeRate.getValue() + completeRate.getDecimal() + completeRate.getUnit());
        } else {
            vo.setCompleteRate("-");
        }
        //累计订单量合计
        SubtotalViewVO accumulativeOrderQuantity = map.get("累计订单量合计");
        if (Objects.nonNull(accumulativeOrderQuantity) && Objects.nonNull(accumulativeOrderQuantity.getValue())) {
            vo.setAccumulativeOrderQuantity(accumulativeOrderQuantity.getValue() + accumulativeOrderQuantity.getDecimal());
        } else {
            vo.setAccumulativeOrderQuantity("0");
        }
        //达成全月百分比
        SubtotalViewVO monthCompleteRate = map.get("达成全月百分比");
        if (Objects.nonNull(monthCompleteRate) && Objects.nonNull(monthCompleteRate.getValue()) &&
                Objects.nonNull(monthCompleteRate.getUnit()) && Objects.nonNull(monthCompleteRate.getDecimal())) {
            vo.setMonthCompleteRate(monthCompleteRate.getValue() + monthCompleteRate.getDecimal() + monthCompleteRate.getUnit());
        } else {
            vo.setMonthCompleteRate("-");
        }
        return vo;
    }

    /**
     * 判断是否是最后一页
     *
     * @param converterResult
     * @param queryOrderMonitorReportRequest
     * @return
     */
    private boolean isLastPage(List<OrderProgressMonitorReportVO> converterResult,
                               QueryOrderMonitorReportRequest queryOrderMonitorReportRequest) {
        boolean flag = false;
        Integer limit = queryOrderMonitorReportRequest.getLimit();
        Integer start = queryOrderMonitorReportRequest.getStart();
        Integer size = converterResult.size();
        log.info("isLastPageOut limit = " + limit + "| start = " + start + " | flag = " + flag);
        //start=0,1000,2000如此递进
        start = start + 1000;
        if (start > size) {
            //最后一页
            flag = true;
            log.info("isLastPageIn limit = " + limit + "| start = " + start + " | flag = " + flag);
            return flag;
        }
        return flag;
    }

    private List<OrderProgressMonitorReportVO> converterVO(List<OrderProgressMonitorReportSDO> list, Boolean isExcel) {
        List<OrderProgressMonitorReportVO> result = list.stream().map(x -> {
            OrderProgressMonitorReportVO vo = new OrderProgressMonitorReportVO();
            BeanUtils.copyProperties(x, vo);

            BigDecimal planDailyAverage = DomUtil.bigDecimalFormatWan(x.getPlanDailyAverage(),2);
            BigDecimal orderQuantity = DomUtil.bigDecimalFormatWan(x.getOrderQuantity(),2);
            BigDecimal accumulativeOrderQuantity = DomUtil.bigDecimalFormatWan(x.getAccumulativeOrderQuantity(),2);
            BigDecimal replyQuantity = DomUtil.bigDecimalFormatWan(x.getReplyQuantity(),2);

            BigDecimal expectedTotalOrderQuantity = null;
            if (x.getExpectedTotalOrderQuantity() != null) {
                expectedTotalOrderQuantity = DomUtil.bigDecimalFormatWan(x.getExpectedTotalOrderQuantity(),2);
            } else {
                expectedTotalOrderQuantity = new BigDecimal("0.00");
            }

            vo.setPlanDailyAverage(DomUtil.amountFormatExcel(planDailyAverage, isExcel));
            vo.setOrderQuantity(DomUtil.amountFormatExcel(orderQuantity, isExcel));
            vo.setAccumulativeOrderQuantity(DomUtil.amountFormatExcel(accumulativeOrderQuantity, isExcel));
            vo.setReplyQuantity(DomUtil.amountFormatExcel(replyQuantity, isExcel));
            BigDecimal tempTaskQuantity = DomUtil.bigDecimalFormatWan(x.getTaskQuantity(),2);
            vo.setTaskQuantity(DomUtil.amountFormatExcel(tempTaskQuantity, isExcel));

            BigDecimal shouldOrderQuantity = new BigDecimal(0);
            //若超进度，当日应下单量展示“0”
            if (x.getShouldOrderQuantity().compareTo(BigDecimal.ZERO) == -1) {
                vo.setShouldOrderQuantity("0");
            } else {
                shouldOrderQuantity = expectedTotalOrderQuantity.subtract(accumulativeOrderQuantity);
                vo.setShouldOrderQuantity(DomUtil.amountFormatExcel(shouldOrderQuantity, isExcel));
            }

            //当日应下单量=0，则当日达成率展示“-”
            if (shouldOrderQuantity.compareTo(BigDecimal.ZERO) == 0) {
                vo.setCompleteRate(null);
            } else {
                vo.setCompleteRate(DomUtil.percentFormat(orderQuantity.divide(shouldOrderQuantity, 4, BigDecimal.ROUND_HALF_UP)));
            }
            vo.setDifferQuantity(DomUtil.amountFormatExcel(orderQuantity.subtract(shouldOrderQuantity), isExcel));

            //月计划当月回复量<=0，则全月达成率展示“-”
            if (replyQuantity.compareTo(BigDecimal.ZERO) == 0) {
                vo.setMonthCompleteRate(null);
            } else {
                vo.setMonthCompleteRate(DomUtil.percentFormat(accumulativeOrderQuantity.divide(replyQuantity, 4, BigDecimal.ROUND_HALF_UP)));
            }

            return vo;
        }).collect(Collectors.toList());
        return result;
    }

    private Result<List<SubtotalViewVO>> initSubtotalViewVO() {
        SubtotalViewVO column1 = new SubtotalViewVO();
        column1.setLabel("当日订单量合计");
        column1.setValue("0");
        column1.setDecimal(".00");
        column1.setUnit("万元");
        SubtotalViewVO column2 = new SubtotalViewVO();
        column2.setLabel("月计划日均量");
        column2.setValue("0");
        column2.setDecimal(".00");
        column2.setUnit("万元");
        SubtotalViewVO column3 = new SubtotalViewVO();
        column3.setLabel("当日应下单量");
        column3.setValue("0");
        column3.setDecimal(".00");
        column3.setUnit("万元");
        SubtotalViewVO column4 = new SubtotalViewVO();
        column4.setLabel("日订单差量");
        column4.setValue("0");
        column4.setDecimal(".00");
        column4.setUnit("万元");
        SubtotalViewVO column5 = new SubtotalViewVO();
        column5.setLabel("当日达成率");
        column5.setValue("0");
        column5.setDecimal(".00");
        column5.setUnit("%");
        SubtotalViewVO column6 = new SubtotalViewVO();
        column6.setLabel("累计订单量合计");
        column6.setValue("0");
        column6.setDecimal(".00");
        column6.setUnit("万元");
        SubtotalViewVO column7 = new SubtotalViewVO();
        column7.setLabel("累计订单差量");
        column7.setValue("0");
        column7.setDecimal(".00");
        column7.setUnit("万元");
        SubtotalViewVO column8 = new SubtotalViewVO();
        column8.setLabel("达成全月百分比");
        column8.setValue("0");
        column8.setDecimal(".00");
        column8.setUnit("%");
        Result result = Result.listSuccess(Lists.newArrayList(column1, column2, column3, column4, column5, column6, column7, column8), 8);
        return result;
    }

    /**
     * 总部订单看板统计方法
     * @param queryRequest 入参
     * @return 结果
     */
    private Result<List<SubtotalViewVO>> getSubtotalViewData(QueryOrderMonitorReportRequest queryRequest) {
        List<OrderProgressMonitorReportSDO> response = orderProgressMonitorReportQueryRepository.statisticalQuery(queryRequest);
        //当月任务量
        BigDecimal replyQuantity = new BigDecimal(0);
        //月计划日均量
        BigDecimal planDailyAverage = new BigDecimal(0);
        //当月应下单量
        BigDecimal shouldOrderQuantity = new BigDecimal(0);
        //日订单差量
        BigDecimal differQuantity = new BigDecimal(0);
        //当日订单金额
        BigDecimal orderQuantity = new BigDecimal(0);
        //累计订单金额
        BigDecimal accumulativeOrderQuantity = new BigDecimal(0);

        for (OrderProgressMonitorReportSDO x:response) {
            replyQuantity = replyQuantity.add(DomUtil.bigDecimalFormatWan(x.getReplyQuantity(),2));
            planDailyAverage = planDailyAverage.add(DomUtil.bigDecimalFormatWan(x.getPlanDailyAverage(),2));

            BigDecimal tmpAccumulativeOrderQuantity = DomUtil.bigDecimalFormatWan(x.getAccumulativeOrderQuantity(),2);
            accumulativeOrderQuantity = accumulativeOrderQuantity.add(tmpAccumulativeOrderQuantity);

            BigDecimal tmpOrderQuantity = DomUtil.bigDecimalFormatWan(x.getOrderQuantity(),2);
            orderQuantity = orderQuantity.add(tmpOrderQuantity);

            BigDecimal tmpExpectedTotalOrderQuantity = null;
            if (x.getExpectedTotalOrderQuantity() == null) {
                tmpExpectedTotalOrderQuantity = new BigDecimal("0.00");
            } else {
                tmpExpectedTotalOrderQuantity = DomUtil.bigDecimalFormatWan(x.getExpectedTotalOrderQuantity(),2);
            }
            BigDecimal tmpShouldOrderQuantity = null;
            if (x.getShouldOrderQuantity().compareTo(BigDecimal.ZERO) == -1) {
                tmpShouldOrderQuantity = new BigDecimal("0.00");
            } else {
                tmpShouldOrderQuantity = tmpExpectedTotalOrderQuantity.subtract(tmpAccumulativeOrderQuantity);
            }
            shouldOrderQuantity = shouldOrderQuantity.add(tmpShouldOrderQuantity);

            BigDecimal tmpDifferQuantity = tmpOrderQuantity.subtract(tmpShouldOrderQuantity);
            differQuantity = differQuantity.add(tmpDifferQuantity);
        }

        //当日达成率 未完成:当日订单金额/当日应下单量 超额完成:（当日订单金额-当日应下单量）/当日应下单量
        BigDecimal completeRate = shouldOrderQuantity.compareTo(BigDecimal.ZERO) > 0 ? orderQuantity.divide(shouldOrderQuantity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).setScale(2) : null;
        //全月百分比
        BigDecimal monthCompleteRate = replyQuantity.compareTo(BigDecimal.ZERO)  > 0 ?
                accumulativeOrderQuantity.divide(replyQuantity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).setScale(2) : null;
        //累计订单差量
        BigDecimal accumulativeDifferQuantity = accumulativeOrderQuantity.subtract(replyQuantity);

        //月计划日均量
        SubtotalViewVO column1 = SubtotalViewVOUtil.getSimpleSubtotalVO("月计划日均量", SubtotalViewVOUtil.YUAN, planDailyAverage);
        //当日应下单量
        SubtotalViewVO column2 = SubtotalViewVOUtil.getSimpleSubtotalVO("当日应下单量", SubtotalViewVOUtil.YUAN, shouldOrderQuantity);
        //当日订单合计
        SubtotalViewVO column3 = SubtotalViewVOUtil.getSimpleSubtotalVO("当日订单量合计", SubtotalViewVOUtil.YUAN, orderQuantity);
        //当日达成率
        SubtotalViewVO column4 = completeRate != null ? SubtotalViewVOUtil.getSubtotalVODeltaUnsigned("当日达成率", SubtotalViewVOUtil.PERCENT, completeRate): getNoDataViewVo("当日达成率");
        //日订单差量
        SubtotalViewVO column5 = SubtotalViewVOUtil.getSimpleSubtotalVO("日订单差量", SubtotalViewVOUtil.YUAN, differQuantity);
        //累计订单合计
        SubtotalViewVO column6 = SubtotalViewVOUtil.getSimpleSubtotalVO("累计订单量合计", SubtotalViewVOUtil.YUAN, accumulativeOrderQuantity);
        //累计订单差量
        SubtotalViewVO column7 = SubtotalViewVOUtil.getSimpleSubtotalVO("累计订单差量", SubtotalViewVOUtil.YUAN, accumulativeDifferQuantity);
        //达成全月百分比
        SubtotalViewVO column8 = monthCompleteRate != null ? SubtotalViewVOUtil.getSubtotalVODeltaUnsigned("达成全月百分比", SubtotalViewVOUtil.PERCENT, monthCompleteRate) : getNoDataViewVo("达成全月百分比");

        List<SubtotalViewVO> subtotalViewVOList = Lists.newArrayList(column1, column2, column3, column4, column5, column6, column7, column8);
        Result result = Result.listSuccess(subtotalViewVOList, subtotalViewVOList.size());
        return result;
    }

    private SubtotalViewVO getNoDataViewVo(String label) {
        SubtotalViewVO v = new SubtotalViewVO();
        v.setLabel(label);
        v.setValue("-");
        return v;
    }

    private int getDay(String date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtils.parse(date));
        int day = calendar.get(Calendar.DAY_OF_MONTH);
//        int monthDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
//        String whenOfMonth = "";
//        if(day <= 10){
//            whenOfMonth = "early";
//        }else if(day > 10 && day <= 20){
//            whenOfMonth = "middle";
//        }else if(day > 20){
//            whenOfMonth = "late";
//        }
//        Object[] array = {whenOfMonth,monthDays,day};
        return day;
    }

}
